import axios from 'axios';
import type { AxiosError, AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
import type { AxiosOptions, RequestInterceptors, Respones, AxiosCustomRequestConfig } from './type';
import AbortAxios from './AbortAxios';

/**
 * 创建一个实体类 AxiosMax
 */
class AxiosMax {
	// axios 实例，通过axios.create()创建
	private axiosInstance: AxiosInstance;
	// 传入的配置
	private options: AxiosOptions;
	// 拦截器
	private interceptors: RequestInterceptors | undefined;
	constructor(options: AxiosOptions) {
		this.axiosInstance = axios.create({
			...options,
		});
		this.options = options;
		this.interceptors = options.interceptors;
		// 对拦截器进行初始化设置
		this.setInterceptors();
	}

	/**
	 * 拦截器注册
	 */
	setInterceptors() {
		// 如果配置中没有传入拦截器， 直接返回
		if (!this.interceptors) {
			return;
		}
		const { requestInterceptors, requestInterceptorsCatch, responseInterceptor, responseInterceptorsCatch } =
			this.interceptors;

		// 创建取消请求实例
		const abortAxios = new AbortAxios();

		// 挂载请求拦截
		this.axiosInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
			// 是否清除重复请求
			const abortRepetitiveRequest =
				(config as unknown as any)?.abortRepetitiveRequest ?? this.options.abortRepetitiveRequest;
			if (abortRepetitiveRequest) {
				// 存储请求标识
				abortAxios.addPending(config);
			}
			if (requestInterceptors) {
				// 如果存在请求拦截器，则将config先交给requestInterceptors做对应的配置
				config = requestInterceptors(config) as InternalAxiosRequestConfig<any>;
			}
			return config;
		}, requestInterceptorsCatch ?? undefined);

		// 挂载响应拦截器
		this.axiosInstance.interceptors.response.use(
			(res: AxiosResponse) => {
				// 取消请求
				res && abortAxios.removePending(res.config);

				if (responseInterceptor) {
					// 如果存在响应拦截器，则将返回值先交给responseInterceptor做处理
					res = responseInterceptor(res);
				}
				// 如果没有配置responseInterceptor，根据options.directlyGetData 配置判断是否直接取得data值
				// if (this.options.directlyGetData) {
				//     res = res.data;
				// }
				return res;
			},
			(err: AxiosError) => {
				if (responseInterceptorsCatch) {
					// 如果存在响应错误拦截器，则将返回值先交给responseInterceptorsCatch做处理
					return responseInterceptorsCatch(this.axiosInstance, err);
				}
				return err;
			},
		);
	}

	/**
	 * 统一请求方法
	 */
	request<T = any>(config: AxiosCustomRequestConfig): Promise<T> {
		return new Promise((resolve, reject) => {
			this.axiosInstance
				.request<any, AxiosResponse<Respones>>(config)
				.then((res) => {
					return resolve(res as unknown as Promise<T>);
				})
				.catch((err) => {
					return reject(err);
				});
		});
	}

	get<T = any>(config: AxiosCustomRequestConfig): Promise<T> {
		return this.request({ ...config, method: 'GET' });
	}
	post<T = any>(config: AxiosCustomRequestConfig): Promise<T> {
		return this.request({ ...config, method: 'POST' });
	}
	put<T = any>(config: AxiosCustomRequestConfig): Promise<T> {
		return this.request({ ...config, method: 'PUT' });
	}
	delete<T = any>(config: AxiosCustomRequestConfig): Promise<T> {
		return this.request({ ...config, method: 'DELETE' });
	}
}

export default AxiosMax;
